package com.xhsj.user.hr.system.service;

import com.xhsj.user.hr.base.BaseParam;
import com.xhsj.user.hr.process.dto.hrEntryProcess.StartEntryApplyDto;
import com.xhsj.user.hr.process.dto.processDefinition.HandleAuditDto;
import com.xhsj.user.hr.process.hrEntryProcess.entity.TbHrApprovalEntryApply;
import com.xhsj.user.hr.process.hrEntryProcess.service.TbHrApprovalEntryApplyService;
import com.xhsj.user.hr.process.message.service.TbProjectMessageService;
import com.xhsj.user.hr.process.processDefinition.query.ProcessNodeQuery;
import com.xhsj.user.hr.process.processDefinition.service.TbGlobalApprovalTaskService;
import com.xhsj.user.hr.process.query.ApprovalQuery;
import com.xhsj.user.security.entity.LoginUser;
import com.xhsj.user.hr.system.dto.SavePostEntryDto;
import com.xhsj.user.hr.system.dto.UpdateUserDetailDto;
import com.xhsj.user.hr.system.entity.TbGlobalUser;
import com.xhsj.user.hr.system.entity.TbHrApprovalDimissionApply;
import com.xhsj.user.hr.system.entity.TbHrZhaopinDemandApply;
import com.xhsj.user.hr.system.mapper.TbGlobalRoleMapper;
import com.xhsj.user.hr.system.mapper.TbGlobalUserMapper;
import com.xhsj.user.hr.system.mapper.TbHrApprovalDimissionApplyMapper;
import com.xhsj.user.hr.system.query.FindDimissionListQuery;
import com.xhsj.user.hr.system.query.UserBaseQuery;
import com.xhsj.user.hr.system.service.TbHrApprovalDimissionApplyService;
import com.xhsj.user.hr.base.BaseService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xhsj.user.hr.system.vo.DimissionApplyAuditTaskVo;
import com.xhsj.user.hr.system.vo.MonthCountVo;
import com.xhsj.user.hr.system.vo.ZhaopinDemandApplyAuditTaskVo;
import com.xhsj.user.utils.DateUtils;
import com.xhsj.user.utils.MessageConstant;
import com.xhsj.user.utils.UserUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.io.Serializable;
import java.util.concurrent.CompletableFuture;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import lombok.extern.slf4j.Slf4j;

import javax.validation.Valid;

/**
 * <p>
 * hr流程-离职申请表 服务实现类
 * </p>
 *
 * @author suxiaolin
 * @since Sep 8, 2020 11:41:49 AM
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
//@CacheConfig(cacheNames = "TbHrApprovalDimissionApply")
public class TbHrApprovalDimissionApplyService extends BaseService<TbHrApprovalDimissionApplyMapper, TbHrApprovalDimissionApply>{
    @Autowired
    private TbHrApprovalDimissionApplyMapper dao;
    @Autowired
    private TbGlobalUserMapper tbGlobalUserMapper;

    @Autowired
    private TbGlobalRoleMapper tbGlobalRoleMapper;

    @Autowired
    private TbGlobalApprovalTaskService tbGlobalApprovalTaskService;

    @Autowired
    private TbProjectMessageService tbProjectMessageService;

    @Autowired
    private TbGlobalUserService tbGlobalUserService;
    // 密码
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Value("${rolekeyname.renshi}")
    private String personnelRole;

	/**
	 * 保存
	 * @author suxiaolin
	 * @date Sep 8, 2020 11:41:49 AM
	 */
    @Override
    //@CacheEvict(cacheNames="TbHrApprovalDimissionApply", allEntries=true)
    public boolean save(TbHrApprovalDimissionApply entity) {
        return super.save(entity);
    }

	/**
	 * 通过id获取数据
	 * @author suxiaolin
	 * @date Sep 8, 2020 11:41:49 AM
	 */
    @Override
    //@Cacheable(key = "#id",sync = true)
    public TbHrApprovalDimissionApply getById(Serializable id) {
        return super.getById(id);
    }

	/**
	 * 通过id删除数据
	 * @author suxiaolin
	 * @date Sep 8, 2020 11:41:49 AM
	 */
    @Override
    //@CacheEvict(cacheNames="TbHrApprovalDimissionApply", allEntries=true)
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

	/**
	 * 批量删除数据
	 * @author suxiaolin
	 * @date Sep 8, 2020 11:41:49 AM
	 */
    //@CacheEvict(cacheNames="SysDict", allEntries=true)
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        return super.removeByIds(idList);
    }

	/**
	 * 分页查询数据
	 * @author suxiaolin
	 * @date Sep 8, 2020 11:41:49 AM
	 */
    //@Cacheable(key = "#data",sync = true)
    public IPage<TbHrApprovalDimissionApply> selectPage(Map<String,Object> data) {
        int currentPage=1;
        if (!Objects.isNull(data.get("page"))) {
            currentPage=(Integer) data.get("page");
        }
        int pageSize=20;
        if (!Objects.isNull(data.get("size"))) {
            pageSize=(Integer) data.get("size");
        }

        Long userId = UserUtils.getLoginAppUser().getUserId();

        TbHrApprovalDimissionApply entity = JSON.parseObject(JSON.toJSONString(data), TbHrApprovalDimissionApply.class);
        entity.setCreateBy(userId);
        Page<TbHrApprovalDimissionApply> page = new Page(currentPage,pageSize);
        QueryWrapper<TbHrApprovalDimissionApply> wrapper = new QueryWrapper(entity);
        return super.selectPage(page, wrapper);
    }

	/**
	 * 查询所有数据
	 * @author suxiaolin
	 * @date Sep 8, 2020 11:41:49 AM
	 */
    @Override
    //@Cacheable(value = "TbHrApprovalDimissionApply",sync = true)
    public List<TbHrApprovalDimissionApply> selectAll() {
        return super.selectAll();
    }


    /**
     * 保存数据
     * @author 苏小林
     * @date 2020/9/8 13:45
     * @param: data
     */
    public void saveData(TbHrApprovalDimissionApply data) throws Exception {
        Long applyUserId = data.getApplyUserId();
        // 查询applyUserId 是否存在
        int count = dao.getApplyUserIdIsExist(applyUserId);
        if (count > 0) {
            throw new Exception("该用户已经提交离职申请");
        }
        super.save(data);
        this.startProcess(data);
    }

    /**
     * 启动流程
     * @author 苏小林
     * @date 2020/9/8 13:46
     * @param: data
     */
    private void startProcess(TbHrApprovalDimissionApply entity) throws Exception {
        LoginUser loginAppUser = UserUtils.getLoginAppUser();
        Long userId = loginAppUser.getUserId();
        HandleAuditDto handleAuditDto = new HandleAuditDto(entity.getId(), userId, userId, 3);
        // 流程启动
        ProcessNodeQuery processNodeQuery = tbGlobalApprovalTaskService.startHandleAudit(handleAuditDto, entity.getDepartmentId());
        entity.setBusinessId(handleAuditDto.getBusinessId());
        // 修改申请信息
        this.updateInfoById(entity,processNodeQuery);

        // 人事主管角色
        Set<String> renshiRoleIds = tbGlobalRoleMapper.getRoleListByRoleKeyName(Arrays.asList(personnelRole));

        renshiRoleIds.addAll((List<String>) processNodeQuery.getRoleIds());
        // 发送消息
        ApprovalQuery approvalQuery =
                new ApprovalQuery(handleAuditDto.getDataId(), MessageConstant.MSG_6, processNodeQuery.getUserId(),
                        renshiRoleIds, 4, UserUtils.getLoginAppUser().getUserId(),entity.getApplyUserName());
        this.sendMessage(approvalQuery);

    }

    public void sendMessage(ApprovalQuery approvalQuery) {
        //保存消息
        CompletableFuture<Void> f = CompletableFuture.runAsync(() -> {
            tbProjectMessageService.sendMessageCommon(approvalQuery);
        });
    }

    /**
     * 修改申请信息
     * @author 苏小林
     * @date 2020/9/8 13:52
     * @param: entity
     * @param: processNodeQuery
     */
    private void updateInfoById(TbHrApprovalDimissionApply entity, ProcessNodeQuery processNodeQuery) {
        entity.setNodeId(processNodeQuery.getNodeId());
        entity.setNodeName(processNodeQuery.getNodeName());
        entity.setUpdateBy(UserUtils.getLoginAppUser().getUserId());
        entity.setUpdateDate(new Date());
        this.updateById(entity);
    }

    /**
     * 查询待审核任务
     * @author 苏小林
     * @date 2020/9/8 14:11
     * @param: data
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.vo.ZhaopinDemandApplyAuditTaskVo>
     */
    public IPage<DimissionApplyAuditTaskVo> findDimissionApplyRunTask(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());

        Long userId = UserUtils.getLoginAppUser().getUserId();
        List<Long> roleIds = tbGlobalUserMapper.getRoleIdsByUserId(userId);
        return dao.findDimissionApplyRunTask(page,userId,roleIds);
    }

    /**
     * 流程审核
     * @author 苏小林
     * @date 2020/9/8 16:39
     * @param: handleAuditDto
     */
    public void processAudit(HandleAuditDto handleAuditDto) throws Exception {
        ProcessNodeQuery processNodeQuery = tbGlobalApprovalTaskService.handleAudit(handleAuditDto);

        TbHrApprovalDimissionApply entity = new TbHrApprovalDimissionApply();
        entity.setId(handleAuditDto.getDataId());
        entity.setBusinessId(handleAuditDto.getBusinessId());
        // 修改招聘申请信息
        this.updateInfoById(entity,processNodeQuery);

        TbHrApprovalDimissionApply byId = dao.selectById(handleAuditDto.getDataId());

        // 发送消息
        ApprovalQuery approvalQuery =
                new ApprovalQuery(handleAuditDto.getDataId(), MessageConstant.MSG_6, processNodeQuery.getUserId(),
                        processNodeQuery.getRoleIds(), 4, UserUtils.getLoginAppUser().getUserId(),byId==null?"":byId.getApplyUserName());
        this.sendMessage(approvalQuery);
    }

    /**
     * 查询历史任务
     * @author 苏小林
     * @date 2020/9/8 16:55
     * @param: baseParam
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.vo.DimissionApplyAuditTaskVo>
     */
    public IPage<DimissionApplyAuditTaskVo> findDimissionApplyHiTask(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());

        Long userId = UserUtils.getLoginAppUser().getUserId();
        return dao.findDimissionApplyHiTask(page,userId);
    }

    /**
     * 查询离职申请列表
     * @author 苏小林
     * @date 2020/9/9 16:59
     * @param: data
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.entity.TbHrApprovalDimissionApply>
     */
    public IPage<TbHrApprovalDimissionApply> findApplyList(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());
        Long userId = UserUtils.getLoginAppUser().getUserId();
        return dao.findApplyList(page,userId);
    }

    /**
     * 查询人事待办列表
     * @author 苏小林
     * @date 2020/11/13 14:13
     * @param: data
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.entity.TbHrApprovalDimissionApply>
     */
    public IPage<TbHrApprovalDimissionApply> findToDoList(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());
        Long userId = UserUtils.getLoginAppUser().getUserId();
        return dao.findToDoList(page,userId);
    }

    /**
     * 查询交接列表
     * @author 苏小林
     * @date 2020/9/9 17:36
     * @param: data
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.entity.TbHrApprovalDimissionApply>
     */
    public IPage<TbHrApprovalDimissionApply> findHandoverList(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());
        Long userId = UserUtils.getLoginAppUser().getUserId();
        return dao.findHandoverList(page,userId);
    }

    /**
     * 查询所有交接列表
     * @author 苏小林
     * @date 2020/11/5 11:41
     * @param: data
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.entity.TbHrApprovalDimissionApply>
     */
    public IPage<TbHrApprovalDimissionApply> findAllHandoverList(BaseParam data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());

        IPage<TbHrApprovalDimissionApply> iPage = dao.findHandoverList(page, null);

        return iPage;
    }

    /**
     * 查询用户是否提交离职申请 且审核完成
     * @author 苏小林
     * @date 2020/9/11 15:14
     * @param: id
     * @return: java.lang.Integer
     */
    public Map<String,Object> findUserWhetherDimission(Long id) {
        return dao.findUserWhetherDimission(id);
    }

    /**
     * 查询每月离职人数
     * @author 苏小林
     * @date 2020/9/14 16:05
     * @param: date
     * @return: int[]
     */
    public int[] getCountByDate(String date) {
        Calendar calendar = Calendar.getInstance();
        //获得当前年
        int year=calendar.get(Calendar.YEAR);

        //获得当前时bai间的月份，月份从0开始所以结果要加1
        int month=calendar.get(Calendar.MONTH)+1;
        //定义数组
        int[] countVIP = new int[month];

        if (StringUtils.isBlank(date)) {
            date = year +"";
        } else {
            if (!date.equals(year+"")) {
                countVIP = new int[12];
            }
        }

        List<MonthCountVo> list = dao.getCountByDate(date);
        // 判断当月时间
        String year1 = String.valueOf(LocalDate.now().getYear());
        MonthCountVo cunrrentCountByDate = null;
        if(year1.equals(date))
            cunrrentCountByDate = dao.getCunrrentCountByDate();
        if (list.size() >0 && list != null) {
            for (int i = 0; i < list.size(); i++) {
                MonthCountVo monthCountVo = list.get(i);
                if (monthCountVo != null) {
                    if(cunrrentCountByDate != null && cunrrentCountByDate.getMonth() == monthCountVo.getMonth()){
                        monthCountVo.setCount(cunrrentCountByDate.getCount());
                    }
                    //填充月份对应的数据
                    countVIP[monthCountVo.getMonth()-1] = monthCountVo.getCount();
                }

            }
        }
        return countVIP;

    }

    /**
     * 查询离职列表
     * @author 苏小林
     * @date 2020/9/15 17:27
     * @param: data
     * @return: com.baomidou.mybatisplus.core.metadata.IPage<com.xhsj.user.hr.system.entity.TbHrApprovalDimissionApply>
     */
    public IPage<TbHrApprovalDimissionApply> findDimissionList(FindDimissionListQuery data) {
        Page<TbHrApprovalDimissionApply> page = new Page(data.getPage(),data.getSize());
        return dao.findDimissionList(page,data);
    }

    public List<Long> findListByLeaveDate(LocalDate now) {
        return dao.findListByLeaveDate(now);
    }


    /**
     * @Description: 离职员工补录保存
     * @Param:com.xhsj.user.hr.system.dto.SavePostEntryDto
     * @return:null
     * @Author: liuqinghua
     * @Date: 2020/11/10
     */
    public void savePostEntry(SavePostEntryDto data) throws Exception {
        if (data.getApply().getUserId()== null) {
            this.saveTbGlobalUser(data);
        }
        // 判断申请表里有没有已经离职了
        if (data.getDimissionApply().getId() == null) {
            int applyUserIdIsExist = dao.getApplyUserIdIsExist(data.getApply().getUserId());
            if (applyUserIdIsExist != 0) {
                throw new Exception("该员工在离职库已存在");
            }
        }

        UpdateUserDetailDto updateUserDetailDto = new UpdateUserDetailDto();
        BeanUtils.copyProperties(data,updateUserDetailDto);
        // 修改相关得用户信息
        updateUserDetailDto.getApply().setSubmitStauts(1);
        tbGlobalUserService.updateUserDetail(updateUserDetailDto);
        UserBaseQuery apply = data.getApply();
        // 保存离职信息
        TbHrApprovalDimissionApply dimissionApply = this.saveDimissionApply(apply, data);
        // 修改用户状态
        this.updateStatus(dimissionApply,apply);
    }

    // 创建新用户
    public SavePostEntryDto saveTbGlobalUser(SavePostEntryDto data) throws Exception {
        // 创建用户
        TbGlobalUser tbGlobalUser = new TbGlobalUser();
        TbGlobalUser byPhoneNumber = tbGlobalUserMapper.findByPhoneNumber(data.getApply().getPhoneNumber());
        if (byPhoneNumber != null) {
            throw new Exception("手机号码已经存在,请更换!");
        }
        BeanUtils.copyProperties(data.getApply(),tbGlobalUser);
        tbGlobalUser.setCreateDate(tbGlobalUser.getCreateDate()==null?new Date():tbGlobalUser.getCreateDate());
        tbGlobalUser.setUpdateDate(tbGlobalUser.getUpdateDate()==null?new Date():tbGlobalUser.getUpdateDate());
        tbGlobalUser.setCreateBy(UserUtils.getLoginAppUser()==null?1:UserUtils.getLoginAppUser().getUserId());
        tbGlobalUser.setUpdateBy(UserUtils.getLoginAppUser()==null?1:UserUtils.getLoginAppUser().getUserId());
        tbGlobalUser.setDelFlag(0);
        if (!tbGlobalUserService.save(tbGlobalUser)) {
            throw new Exception("创建新用户异常");
        }
        data.getApply().setUserId(tbGlobalUser.getUserId());
        return data;
    }

    // 修改用户状态
    public void updateStatus(TbHrApprovalDimissionApply dimissionApply,UserBaseQuery apply){
        LocalDate now = LocalDate.now();
        if (dimissionApply.getLeaveDate() != null) {
            if (DateUtils.date2LocalDate(dimissionApply.getLeaveDate()).isBefore(now) || DateUtils.date2LocalDate(dimissionApply.getLeaveDate()).isEqual(now))  {
                TbGlobalUser tbGlobalUser = new TbGlobalUser();
                tbGlobalUser.setUserId(apply.getUserId());
                tbGlobalUser.setStatus(1);
                tbGlobalUserService.updateById(tbGlobalUser);
            }
        }
    }
    // 保存离职信息
    public TbHrApprovalDimissionApply saveDimissionApply(UserBaseQuery apply,SavePostEntryDto data) throws Exception {
        TbHrApprovalDimissionApply dimissionApply = data.getDimissionApply();
        dimissionApply.setApplyUserId(apply.getUserId());
        dimissionApply.setDepartmentId(apply.getDepartmentId());
        dimissionApply.setPositionId(apply.getPositionId());
        dimissionApply.setApplyUserName(apply.getFullName());
        LocalDate localDate = null;
        Date arrivalDate = apply.getArrivalDate();
        if (arrivalDate != null) {
            Instant instant = arrivalDate.toInstant();
            ZoneId zone = ZoneId.systemDefault();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
            localDate = localDateTime.toLocalDate();
        }

        dimissionApply.setArrivalDate(DateUtils.localDate2Date(localDate));
        if (!super.save(dimissionApply)) {
            throw new Exception("保存离职信息异常");
        }
        return dimissionApply;
    }
}
